<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>响应式原理</title>
	<link rel="stylesheet" href="">
</head>
<body>
	
</body>
<script>
	
	/* 目标

		1. 验证如果对象中存在数组，是否为响应式

		2. 如果不是响应式，提供相应算法，将其转换为响应式
	*/


	let data = {
		age: [12, 23, 34, {arr1: [1, 2]}],
		name: {
			na1: 'ok',
			na2: [1, 2, 3]
		}
	}


	// 008中提供的算法,验证第一个问题
	function defineResponse(obj, key, value, enumerable) {
		Object.defineProperty(obj, key, {
			enumerable: enumerable == undefined ? true : !!enumerable,
			get: ()=>{
				return `获取到了${key}的值：${value}`;
			},
			set: (newValue)=>{
				value = newValue;
				console.log(`设置${key}的值为${value}`);
			}
		})
	}
	// defineResponse(data, 'age', data['age']);
	// 结果为age是响应式，但是age中元素不是响应式


	// 使用遍历的方法将数组中的元素转换为响应式
	function response(obj) {
		let keys = Object.keys(obj);

		for(let i = 0; i < keys.length; i++) {
			if(Array.isArray(obj[keys[i]])) {
				response(obj[keys[i]]);
			} else {
				defineResponse(obj, keys[i], obj[keys[i]]);
			}
		}

	}
	// response(data);
	/* 分析
		1. 为什么可以使用上述的方法对数组进行响应式，我的分析有以下几点
			-1 数组的访问形式：
			-2 keys返回的数组成员类型

		2. 数组的访问形式
			数组的访问形式可以是arr[0], 还可以是arr['0']，不信可以自行测试。正是这一点，我们发现数组和对象的访问形式产生了一种莫名的契合度，常说数组就是对象，也许这也是一种体现。

			这是这种去契合度，才为Object》defineProprety api转换数组提供了可能性。

		3. 同时Object.keys()返回的数组成员是字符串类型，恰好为上面的数组提供了方便，如果不是字符串类型，也不怕，我们也可以手动转换。
	*/


	// 扩展：对上述算法进行一点点的修改，完成对象的响应式的转换。
	function response(obj) {
		let keys = Object.keys(obj);

		for(let i = 0; i < keys.length; i++) {
			if(typeof(obj[keys[i]]) === 'object' ) {
				response(obj[keys[i]]);
			} else {
				defineResponse(obj, keys[i], obj[keys[i]]);
			}
		}

	}
	response(data);


	/* 总结

		1. 通过逐渐增强，我们已经完成了复杂数据类型的响应式转换

		2. 存在的问题
			-1 上述的问题存在一点小的瑕疵，对于动态添加的元素，是否也具有响应式？ 
	*/ 



</script>
</html>